# -*- coding: UTF-8 -*-

from urllib.request import build_opener, HTTPCookieProcessor, Request
from http.cookiejar import CookieJar
import io
import random
import json


def encode_data(data):
    try:
        return bytes(data, 'utf-8')
    except:
        return bytes(data)


def decode_data(data):
    return io.StringIO(data.read().decode('utf-8'))


class Controller(object):
    _sid = None

    def __init__(self, base_url, timeout):
        cookie_jar = CookieJar()
        opener = build_opener(HTTPCookieProcessor(cookie_jar))
        self._opener = opener

        self.base_url = base_url
        self.timeout = timeout

    def __call__(self, url, **kwargs):
        return self._rpc_call(url, **kwargs)

    def _rpc_call(self, url, **kwargs):

        # 1. url 地址
        base_url = self.base_url
        full_url = base_url + url

        print('odoo jsonrpc, url:', full_url)
        print('odoo jsonrpc, kws:', kwargs)

        # 2. 请求的数据
        data = {
            "jsonrpc": "2.0",
            "method": "call",
            "params": kwargs,
            "id": random.randint(0, 1000000000),
        }
        # print('data:', data)

        data_json = json.dumps(data)

        request = Request(url=full_url, data=encode_data(data_json))

        # 3. 请求头
        request.add_header('Content-Type', 'application/json')

        # 31. 请求头中添加 session
        url_auth = '/web/session/authenticate'
        url_info = '/web/session/get_session_info'
        urls_auth = [url_auth, url_info]

        session_id = Controller._sid
        if session_id:
            if url not in urls_auth:
                request.add_header('X-Openerp-Session-Id', session_id)

        # print('request session_id', session_id)
        # print('request', request.headers)

        # 4. 发请求, 获得响应
        timeout = self.timeout
        response = self._opener.open(request, timeout=timeout)
        # print('response:', response)

        # 41 从响应头中, 获取 session_id, 暂存
        # 42 如果是 浏览器中 发请求,
        # 421 响应头中携带的 session_id 自动存cookie
        # 422 且 无法通过代码 在响应头中, 截取 session_id
        # 423 且 后续再发送其他请求时, 自动携带 cookie
        # 43 如果是 无cookie的场景  发请求, 如 wx小程序、移动端 android/iOS、前端命令行跑测试
        # 431 响应头中携带的 session_id, 可以被代码 截取, 暂存
        # 431 且, 后续再发送其他请求时, 将暂存的 session_id 写入 请求头文件中

        if url in urls_auth:
            # print('url', url)
            headers = response.headers
            # print('response headers', headers)

            cookie = headers.get('Set-Cookie')
            if cookie:
                session_id = cookie[11:51]
                # print('session_id', session_id)
                Controller._sid = session_id

        # 5. 响应结果获取数据
        data = json.load(decode_data(response))
        # print('response:', data)

        # 51. 响应结果中有 error, 客户端 自行处理
        error = data.get('error')
        if error:
            print('error', error)
            raise error

        # 52. 响应结果中有 result, 客户端 后续继续处理
        result = data.get('result')
        return result
